package plgnet

import (
	"dgo/MyProj/PrjHttpUtils"
	"dgo/goutils/gohttp"
	"dgo/goutils/utils"
	"gitee.com/ymofen/supervalue"
	"net/http"
	"time"
)

type InnerHttp struct {
	ownerPlug interface{}

	UseSvCache bool

	// 注册的uri
	api_uri_map utils.GSyncMapGroup

	//
	api_prefix string

	Tracelst *utils.SyncCycleList

	TraceFlag byte

	// 是否运行跨域
	Http_allow_cross_access bool
}

func NewInnerHttp(ownerPlg interface{}) *InnerHttp {
	rval := &InnerHttp{ownerPlug: ownerPlg}
	return rval
}

func (this *InnerHttp) CheckRegisterApi(key, uri string, fn http.HandlerFunc) {
	uri0 := this.api_uri_map.Get(key, "").(string)
	if uri0 != uri {
		if len(uri0) > 0 {
			gohttp.UnHandle(uri)
		}
		this.api_uri_map.Set(key, uri)
		if len(uri) > 0 {
			gohttp.HandleFunc(uri, fn)
		}
	}
}

func (this *InnerHttp) FillHttpStatus(json *wrapper.SuperValue) {
	json.SetKeyValue("api-prefix", this.api_prefix)
	json.SetKeyValue("trace-debug", this.TraceFlag)
	json.SetKeyValue("allow-cross", this.Http_allow_cross_access)
	json.SetKeyValue("handle-cnt", this.api_uri_map.Count())
}

func (this *InnerHttp) CheckRegisterApiURI(urisuffix string, fn http.HandlerFunc) {
	_, urisuffix = utils.CheckAddPrefix(urisuffix, "/")
	this.CheckRegisterApi(urisuffix, this.api_prefix+urisuffix, fn)
}

func (this *InnerHttp) CheckRegisterJSONApi(urisuffix string, fn func(req *PrjHttpUtils.HttpRec)) {
	this.CheckRegisterApiURI(urisuffix, func(w http.ResponseWriter, r *http.Request) {
		req := PrjHttpUtils.NewHttpRec(w, r)
		if this.Http_allow_cross_access {
			PrjHttpUtils.AllowCrossAccessSet(req.RespW)
		}
		if r.Method == "OPTIONS" {
			req.ResponseText("succ")
			return
		}
		req.DecodeRequestBodyAsJSONCache(this.UseSvCache)
		if this.UseSvCache {
			defer req.Req.Clear()
		}
		this.CheckInitial(req)
		fn(req)
	})
}

func (this *InnerHttp) UnRegisterApi(urisuffix string) {
	_, urisuffix = utils.CheckAddPrefix(urisuffix, "/")
	uri0 := this.api_uri_map.Get(urisuffix, "").(string)
	if len(uri0) > 0 {
		gohttp.UnHandle(urisuffix)
	}
	this.api_uri_map.Remove(urisuffix)
}

func (this *InnerHttp) unRegister() {
	this.api_uri_map.Range(func(key, value interface{}) bool {
		gohttp.UnHandle(value.(string))
		return true
	})
}

func (this *InnerHttp) Release() {
	this.unRegister()
	this.ownerPlug = nil
}

func (this *InnerHttp) GetApiPrefix() string {
	return this.api_prefix
}

func (this *InnerHttp) CheckInitial(req *PrjHttpUtils.HttpRec) {
	if this.Http_allow_cross_access {
		PrjHttpUtils.AllowCrossAccessSet(req.RespW)
	}

	if this.TraceFlag == 1 {
		var sb utils.BytesBuilder
		sb.Appendf("[%s]请求参数\n", req.ClientAddr())
		sb.Appendf("url:%s\n", req.ReqR.URL.String())
		sb.Appendf("Method:%s\n", req.ReqR.Method)
		PrjHttpUtils.GetRequestHeader(req.ReqR.Header, ":", "\n", &sb)
		sb.Appendf("\n")
		sb.Write(req.BodyBuf)
		sb.Appendf("\n")
		t1 := time.Now()
		req.OnResponseFunc = func(respHeader http.Header, body []byte) {
			sb.Appendf("响应(%d ms)\n", time.Since(t1).Milliseconds())
			PrjHttpUtils.GetRequestHeader(respHeader, ":", "\n", &sb)
			sb.Appendf("\n")
			sb.Write(body)
			sb.Appendf("\n")
			this.Tracelst.LogMsg("%s", sb.String())
		}
	}
}

func (this *InnerHttp) ReloadConf(conf *wrapper.SuperValue) (err error) {

	if this.Tracelst == nil {
		this.Tracelst = utils.NewSyncCycleList()
	}

	if conf == nil {
		return
	}

	conf.CheckExistsStrFunc("http-allow-cross-access", func(strv string) {
		this.Http_allow_cross_access = utils.TryStrToBool(strv, false)
	})

	this.TraceFlag = byte(conf.IntByName("trace-debug", 0))

	conf.CheckExistsStrFunc("api-prefix", func(strv string) {
		if len(strv) == 0 {
			if len(this.api_prefix) > 0 {
				this.unRegister()
			}
		} else {
			_, strv = utils.CheckTrimSuffix(strv, "/")
			if this.api_prefix != strv {
				if len(this.api_prefix) > 0 {
					this.unRegister()
				}
				this.api_prefix = strv
			}
		}
	})
	return
}
